package com.jtpay.payresulthelper.util;

import android.text.TextUtils;
import android.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;


public final class PayDESUtil {
    private static final String LOG_TAG = "PayDESUtil ";
    private static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";
    private static final String ALGORITHM = "DES";
    private static Cipher mCipher = null;
    private static final String DES_KEY_DEF = "wolegequ";
    private static final String DES_KEY_VERIFY_DEF = "dsen";

    private static void log(String str, boolean save) {
        String logStr = LOG_TAG + str;
        LogUtil.log(logStr);
        //save
        if (save)
            ExceptionUtil.getInstance().saveExceptionFile(logStr);
    }

    static {
        try {
            mCipher = Cipher.getInstance(ALGORITHM_DES);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            log("static NoSuchAlgorithmException = " + e.getMessage(), true);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            log("static NoSuchPaddingException = " + e.getMessage(), true);
        }
    }

//    private static final MessageDigest getMessageDigest() {
//        String algorithm = "MD5";
//        try {
//            return MessageDigest.getInstance(algorithm);
//        } catch (NoSuchAlgorithmException e) {
//            throw new IllegalArgumentException("No such algorithm ["
//                    + algorithm + "]");
//        }
//    }


    private static String translate(String key, String data, int mode) {
        try {
            byte[] byteSrc = data.getBytes();
            if (mode == Cipher.DECRYPT_MODE) {
                byteSrc = Base64.decode(data, Base64.DEFAULT);
            }
            String keyMd5 = getMd5(key);
            if (TextUtils.isEmpty(keyMd5) || keyMd5.length() < 8) {
                return null;
            }
            String md5 = keyMd5.substring(0, 8).toUpperCase();
            DESKeySpec dks = new DESKeySpec(md5.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
            Key secretKey = keyFactory.generateSecret(dks);
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(md5.getBytes());
            mCipher.init(mode, secretKey, paramSpec);
            byte[] result = mCipher.doFinal(byteSrc);
            if (mode == Cipher.ENCRYPT_MODE) {
                return Base64.encodeToString(result, Base64.DEFAULT);
            } else {
                return new String(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log("translate Exception = " + e.getMessage(), true);
        }
        return null;
    }


    /**
     * @param key  des key
     * @param data source data
     * @return string
     */
    public static String encode(String key, String data) {
        try {
            return translate(key, data, Cipher.ENCRYPT_MODE).replace("+", "-").
                    replace("/", "_").replace("=", "~").replace("\r", "").replace("\n", "");
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * @param key  des key
     * @param data source data
     * @return string
     */
    public static String decode(String key, String data) {
        data = data.replace("-", "+").replace("_", "/").replace("~", "=");
        try {
            return translate(key, data, Cipher.DECRYPT_MODE);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * @param data source data
     * @return string
     */
    public static String encodeVerifyDef(String key, String data) {
        return encode(DES_KEY_VERIFY_DEF + key, data);
    }

    /**
     * @param data source data
     * @return string
     */
    public static String decodeVerifyDef(String key, String data) {
        return decode(DES_KEY_VERIFY_DEF + key, data);
    }

    /**
     * @param data source data
     * @return string
     */
    public static String encodeDef(String data) {
        return encode(DES_KEY_DEF, data);
    }

    /**
     * @param data source data
     * @return string
     */
    public static String decodeDef(String data) {
        return decode(DES_KEY_DEF, data);
    }

    private static String getMd5(String key) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(key.getBytes());
            byte[] bResult = md.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : bResult) {
                int bt = b & 0xff;
                if (bt < 16) {
                    sb.append(0);
                }
                sb.append(Integer.toHexString(bt));
            }
//            String result = sb.toString().toUpperCase();
//            log("getMd5 result = " + result, false);
            return sb.toString().toUpperCase();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            log("getMd5 NoSuchAlgorithmException = " + e.getMessage(), true);
        }
        return null;
    }
}